package com.suray.wcs.web.system.controller;

import com.suray.basic.wcs.plc.pojo.Robot;
import com.suray.basic.wcs.plc.pojo.TaskSend;
import com.suray.commin.annotation.InterfaceLog;
import com.suray.commin.annotation.Log;
import com.suray.commin.core.controller.BaseController;
import com.suray.commin.core.controller.ResponseData;
import com.suray.commin.core.page.TableDataInfo;
import com.suray.commin.enmus.BusinessType;
import com.suray.wcs.service.core.util.SocketSendUtil;
import com.suray.wcs.service.core.util.WeightterUtil;
import com.suray.wcs.service.enums.DeviceType;
import com.suray.wcs.service.init.device.DeviceManager;
import com.suray.wcs.service.newled.LedShowData;
import com.suray.wcs.service.pojo.BaseEum;
import com.suray.wcs.service.pojo.Device;
import com.suray.wcs.service.pojo.MachHandTaskRequest;
import com.suray.wcs.service.robot.ToRobot;
import com.suray.wcs.service.system.entity.DeviceDB;
import com.suray.wcs.service.system.entity.MachineTaskDB;
import com.suray.wcs.service.system.service.impl.DeviceDBServiceImpl;
import com.suray.wcs.service.system.service.impl.MachineTaskServiceImpl;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @param
 * @author WX
 * @since 2019年11月12日
 */
@RestController
@RequestMapping("/device")
public class DeviceDBController extends BaseController {

    @Autowired
    private DeviceDBServiceImpl devicedbServiceImpl;
    @Autowired
    private MachineTaskServiceImpl machineTaskService;

    private Logger log = LoggerFactory.getLogger(this.getClass());


    /**
     * 查找接口
     *
     * @throws Exception
     */
    @PreAuthorize("@ss.hasPermi('device:list')")
    @GetMapping(value = "/list")
    @ResponseBody
    @ApiOperation("按条件查找设备")
    public TableDataInfo getTaskPage(Device device) {
        DeviceDB devicedb = TransformDb(device);
        startPage();
        List<DeviceDB> deviceList = devicedbServiceImpl.findDeviceList(devicedb, devicedb.getType());
        return getDataTable(deviceList);
    }

    /**
     * 新增设备
     *
     * @throws Exception
     */
    @PreAuthorize("@ss.hasPermi('device:add')")
    @Log(title = "设备管理", method = "新增设备", businessType = BusinessType.INSERT)
    @PostMapping(value = "/insertDevice")
    @ResponseBody
    @ApiOperation("新增设备")
    public ResponseData insertDevice(@RequestBody Device device) {
        DeviceDB devicedb = TransformDb(device);
        if (StringUtils.isEmpty(device.getIp())) {
            return ResponseData.error("设备IP不存在");
        }
        if (devicedb.getPort() == null) {
            return ResponseData.error("设备端口不存在");
        }
        if (devicedb.getType() == null) {
            return ResponseData.error("设备类型不存在");
        }
        devicedbServiceImpl.insertDevice(devicedb);
        return ResponseData.success("插入成功");
    }

    /**
     * 修改是否启用
     *
     * @param devicedb
     * @return
     */
    @Log(title = "设备管理", method = "修改是否启用", businessType = BusinessType.UPDATE)
    @ApiOperation("修改是否启用")
    @PostMapping("/changeDisable")
    @PreAuthorize("@ss.hasPermi('device:edit')")
    public ResponseData changeDisable(@Validated @RequestBody DeviceDB devicedb) {
        return toAjax(devicedbServiceImpl.updateDisableById(devicedb));
    }

    /**
     * 更新设备
     *
     * @throws Exception
     */
    @PreAuthorize("@ss.hasPermi('device:edit')")
    @Log(title = "设备管理", method = "更新设备", businessType = BusinessType.UPDATE)
    @PostMapping(value = "/updateDevice")
    @ResponseBody
    @ApiOperation("更新设备")
    public ResponseData updateDevice(@RequestBody Device device) {
        DeviceDB devicedb = TransformDb(device);
        if (devicedb.getId() == null) {
            return ResponseData.error("设备ID不存在");
        } else if (devicedb.getIp().isEmpty()) {
            return ResponseData.error("设备IP不存在");
        } else if (devicedb.getPort() == null) {
            return ResponseData.error("设备端口不存在");
        } else if (devicedb.getType() == null) {
            return ResponseData.error("设备类型不存在");
        } else {
            devicedbServiceImpl.updateDevice(devicedb);
            return ResponseData.success("查询成功");
        }
    }

    @PreAuthorize("@ss.hasPermi('device:query')")
    @RequestMapping(value = "/queryDeviceType", method = RequestMethod.GET)
    @ApiOperation("查询设备类型")
    public ResponseData queryDeviceType() {
        List<DeviceType> deviceManagerType = (Arrays.asList(DeviceType.values()));
        List<BaseEum> deviceTypeList = new ArrayList<BaseEum>();
        for (DeviceType deviceType : deviceManagerType) {
            deviceTypeList.add(new BaseEum(deviceType.getValue(), deviceType.toString()));
        }
        return ResponseData.success("查询完成", deviceTypeList);
    }

    /**
     * 机械手任务手动下发
     *
     * @throws Exception
     */
    @PostMapping(value = "/machHandTask")
    @ResponseBody
    @ApiOperation("机械手任务手动下发")
    @InterfaceLog(value = "机械手任务手动下发")
    public ResponseData machHandTask(@RequestBody MachHandTaskRequest machHandTaskRequest) {
        if (machHandTaskRequest == null) {
            return ResponseData.error("机械手参数为空,任务下发失败");
        }
        if (machHandTaskRequest.getProductType() == null) {
            return ResponseData.error("产品重量为空,任务下发失败");
        }
        if (StringUtils.isEmpty(machHandTaskRequest.getRobotNo())) {
            return ResponseData.error("机械手设备编号为空,任务下发失败");
        }
        if (StringUtils.isEmpty(machHandTaskRequest.getStartStation())) {
            return ResponseData.error("机械手任务起始工位为空,任务下发失败");
        }
        if (StringUtils.isEmpty(machHandTaskRequest.getEndStation())) {
            return ResponseData.error("机械手任务目的工位为空,任务下发失败");
        }
        if (machHandTaskRequest.getSortNum() == null || machHandTaskRequest.getSortNum() == 0) {
            return ResponseData.error("机械手任务分拣数量为0,任务下发失败");
        }
        // 根据机械臂设备编号找到机械臂对象
        Robot robot = DeviceManager.getByRobotNo(machHandTaskRequest.getRobotNo());
        MachineTaskDB machineTaskDB = createTaskDB(machHandTaskRequest.getRobotNo(), machHandTaskRequest.getProductType(), machHandTaskRequest.getStartStation(), machHandTaskRequest.getEndStation(), machHandTaskRequest.getSortNum());
        TaskSend taskSend = new TaskSend(machHandTaskRequest.getProductType(), machineTaskDB.getTaskId(), machHandTaskRequest.getStartStation(), machHandTaskRequest.getEndStation(), machHandTaskRequest.getSortNum());
        long curtime = System.currentTimeMillis();
        robot.getRobotHeart().getTaskSendCommand().offer(taskSend);
        ToRobot toRobot = ToRobot.getInstance(robot);
        toRobot.resReceiveResult(taskSend, curtime);

        return ResponseData.success("机械手任务下发成功");
    }

    /**
     * 前后端交互对象转换成DB对象
     *
     * @param device
     * @return
     */
    private DeviceDB TransformDb(Device device) {
        DeviceDB devicedb = new DeviceDB();
        BeanUtils.copyProperties(device, devicedb);
        devicedb.setType(device.getType() == null ? null : DeviceType.parsePlcDeviceType(device.getType()));
        return devicedb;
    }

    /**
     * 扫码开启
     */
    @ApiOperation(value = "扫码开启")
    @PreAuthorize("@ss.hasPermi('device:edit')")
    @Log(title = "设备管理", method = "扫码开启", businessType = BusinessType.OTHER)
    @GetMapping("/scannerOpen")
    @ResponseBody
    public ResponseData scannerOpen(@RequestParam String ip, String port) {
        SocketSendUtil socketSendUtil = SocketSendUtil.getSocketSendUtil(ip, Integer.parseInt(port));
        try {
            socketSendUtil.startScanner();
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseData.error("扫码开启失败");
        }
        return ResponseData.success("扫码开启");
    }

    /**
     * 扫码关闭
     */
    @ApiOperation(value = "扫码关闭")
    @PreAuthorize("@ss.hasPermi('device:edit')")
    @Log(title = "设备管理", method = "扫码关闭", businessType = BusinessType.OTHER)
    @GetMapping("/scannerClose")
    @ResponseBody
    public ResponseData scannerClose(@RequestParam String ip, String port) {
        try {
            SocketSendUtil socketSendUtil = SocketSendUtil.getSocketSendUtil(ip, Integer.parseInt(port));
            socketSendUtil.closeScanner();
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseData.error("扫码关闭失败");
        }
        return ResponseData.success("扫码关闭");
    }

    /**
     * 称重
     */
    @ApiOperation(value = "称重")
    @PreAuthorize("@ss.hasPermi('device:edit')")
    @Log(title = "设备管理", method = "称重", businessType = BusinessType.OTHER)
    @GetMapping("/weightStart")
    @ResponseBody
    public ResponseData weightStart(@RequestParam String ip, String port) {
        try {
            WeightterUtil weightterUti = new WeightterUtil(ip, port);
            double weight = weightterUti.getWeight();
            if (weight > 0) {
                return ResponseData.success("称重成功", weight);
            } else {
                return ResponseData.error("称重失败");
            }
        } catch (Exception e) {
            return ResponseData.error("网络连接失败");
        }
    }

    @GetMapping("/ledMsg")
    @ResponseBody
    public ResponseData LedMsg(Integer deviceId, String ip, Integer port, String ledContent) {
        try {
            log.info("发送Led信息" + ledContent);
            LedShowData.ledSend(deviceId, null, ledContent);
            return ResponseData.success();
        } catch (IOException e) {
            return ResponseData.error("发送led信息 通讯失败");
        }
    }


    /**
     * 插入机械臂任务
     *
     * @param machineNo
     * @param productType
     * @param startStation
     * @param endStation
     * @param cargoCount
     */
    private MachineTaskDB createTaskDB(String machineNo, Integer productType, String startStation, String endStation, Integer cargoCount) {
        MachineTaskDB machineTaskDB = new MachineTaskDB();
        machineTaskDB.setMachineNo(machineNo);
        machineTaskDB.setStartStation(startStation);
        machineTaskDB.setEndStation(endStation);
        machineTaskDB.setProductType(productType);
        machineTaskDB.setCargoCount(cargoCount);

        machineTaskService.insertMachineTask(Collections.singletonList(machineTaskDB));

        return machineTaskDB;
    }
}
